package camid.distribution.lifecycle.perclient;

import java.util.List;

import camid.distribution.activeobject.ObjectRegistry;
import camid.distribution.activeobject.ObjectScheduler;
import camid.distribution.events.FutureNotificator;
import camid.distribution.lifecycle.DefaultEntityFactory;
import camid.distribution.lifecycle.AbstractLifecycleManager;

public class PerClientLifecycleManager extends AbstractLifecycleManager {

	private LeasingManager manager;
	private Long defaultLease;
	
	public static Long DEFAULT_LEASE = 600000L;
	
	public PerClientLifecycleManager(ObjectRegistry objectRegistry) {
		super(objectRegistry);
		manager = new LeasingManager(objectRegistry);
		defaultLease = DEFAULT_LEASE;
	}
	
	public PerClientLifecycleManager(ObjectRegistry objectRegistry, Long lease) {
		super(objectRegistry);
		manager = new LeasingManager(objectRegistry);
		defaultLease = lease;
	}

	public PerClientLifecycleManager(ObjectRegistry objectRegistry,
			FutureNotificator futureNotificator) {
		super(objectRegistry, futureNotificator);
		manager = new LeasingManager(objectRegistry);
		defaultLease = DEFAULT_LEASE;
	}

	/* (non-Javadoc)
	 * @see camid.distribution.lifecycle.perclient.ILifecycleManager#shutdown()
	 */
	public void shutdown() 
	{
		if(agent != null)
		{
			agent.shutdown();
		}
		manager.shutdown();
	}

	/* (non-Javadoc)
	 * @see camid.distribution.lifecycle.perclient.ILifecycleManager#newObject(java.lang.String, java.lang.Class, camid.distribution.lifecycle.DefaultObjectBuilder)
	 */
	public ObjectScheduler newObject(String objectId, Class<?> entityClass,
			DefaultEntityFactory defaultObjectBuilder) throws InstantiationException, IllegalAccessException {
		startLeasingThread();
		Object entity = defaultObjectBuilder.newEntity(entityClass);
		ObjectScheduler scheduler = new ObjectScheduler(objectId, entity);
		manager.newLease(scheduler, defaultLease);
		notifyObjectCreation(objectId, entityClass);
		return scheduler;
	}

	/* (non-Javadoc)
	 * @see camid.distribution.lifecycle.perclient.ILifecycleManager#destroyObject(java.lang.String)
	 */
	public ObjectScheduler destroyObject(String objectId) 
	{
		ObjectScheduler scheduler = manager.removeLease(objectId);
		notifyObjectDestruction(objectId);
		return scheduler;
	}
	
	private LeasingAgent agent;
	private Thread agentThread;
	
	private void startLeasingThread() 
	{
		if( agent == null )
		{
			agent = new LeasingAgent(this);
			agentThread = new Thread(agent);
			agentThread.start();
		}
	}

	/* (non-Javadoc)
	 * @see camid.distribution.lifecycle.perclient.ILifecycleManager#hasObject(java.lang.String)
	 */
	public boolean hasObject(String objectId) {
		boolean result = manager.getObject(objectId) != null;
		return result;
	}

	/* (non-Javadoc)
	 * @see camid.distribution.lifecycle.perclient.ILifecycleManager#getObject(java.lang.String)
	 */
	public ObjectScheduler getObject(String objectId) {
		ObjectScheduler scheduler = manager.getObject(objectId);
		return scheduler;
	}

	public List<String> getLeasedObjectIds() 
	{	
		return manager.getObjectIds();
	}

	public Lease getLease(String objectId) 
	{
		Lease lease = manager.getLease(objectId);
		return lease;
	}
	
	@Override
	public ObjectScheduler insertObject(String objectId, Object entity)
	{
		ObjectScheduler scheduler = null;
		if(manager.hasLease(objectId))
		{
			scheduler = manager.getObject(objectId);
			scheduler.setEntity(entity);
		}
		else
		{
			scheduler = new ObjectScheduler(objectId, entity);
			manager.newLease(scheduler, defaultLease);
		}
		notifyObjectCreation(objectId, entity.getClass());
		return scheduler;
	}

}
